Skip to content

feat: fzf inline editing completion#1191

Open
ArkhamKnight25 wants to merge 1 commit intoros2:rollingfrom
ArkhamKnight25:rolling
Open

feat: fzf inline editing completion#1191
ArkhamKnight25 wants to merge 1 commit intoros2:rollingfrom
ArkhamKnight25:rolling

Conversation

@ArkhamKnight25
Copy link

@ArkhamKnight25 ArkhamKnight25 commented Feb 17, 2026

@fujitatomoya san, Please review the changes. Thank you.

Description

Added shell scripts (Bash + Zsh) that lets us pick topics, services and nodes with fzf, then drop us back on the command line so we can add flags before running. If you cancel fzf, it falls back to ros2cli's default picker. Should I keep this fallback or remove it?

Fixes #1184

Is this user-facing behavior change?

Yes, now we can easily hit up and down arrow keys to get the executed commands from the terminal.

Please let me know of any changes that are needed. It was interesting to learn about cli workflows. Thanks.

Signed-off-by: ArkhamKnight25 <amritamber3112@gmail.com>
Copy link
Collaborator

@fujitatomoya fujitatomoya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ArkhamKnight25 thanks for creating PR.

IMO, i am not inclined to take this approach, there could be many downsides with this PR because those shell scripts are not small shim... originally those shim scripts are meant to register ros2cli python application with our shell’s completion framework. (https://kislyuk.github.io/argcomplete/)

i believe the fundamental issue is that the scripts shadow the entire ros2 command with a shell function....

fi

history -s -- "$full_cmd"
eval -- "$full_cmd"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this a security concern? the user is presented with a pre-filled prompt they can edit freely, and the result is passed to eval?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you are right, using eval will introduce a security risk, allowing execution of additional commands, will not use it.


if ! command -v fzf &> /dev/null; then
echo "fzf is not installed. Install with: sudo apt install fzf" >&2
command ros2 "$@"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it replaces the ros2 binary with a shell function for the entire session. that said, this will intercept all ros2 calls, including from other scripts. it changes behavior for every user who sources this file, not just in interactive completion contexts.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes shadowing ros2() will indeed start intercepting everything

Comment on lines +10 to +13
case "$*" in
"topic echo" | "topic info" | "topic hz" | \
"topic bw" | "topic pub" | "topic type" | \
"topic delay")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this matches "$*" (all args joined by space) against exact strings. i think there are some problems here,

  • ros2 topic echo (double space) does not.
  • ros2 --log-level debug topic echo does not match.
  • any future subcommands (e.g., ros2 topic inspect) won't be caught without updating these scripts.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, it is fragile, will remove the pattern matching.

@ArkhamKnight25
Copy link
Author

ArkhamKnight25 commented Feb 19, 2026

@fujitatomoya Thank you for reviewing it.
Okay so after hitting enter on ros2 topic echo, and then again selecting the method, to add the additional arguments,
Im thinking of fixing this with some python side changes then, the idea is to add an interactive_select_with_edit() helper in helpers.py. After the fzf selection, it would show a readline prompt pre-filled with the selected topic. The user could then type extra flags and hit enter, or just hit enter to run it.

So the flow would look something like this:

amrit@system25:~/ros2_ws$ ros2 topic echo
Select topic to echo:
> /chatter

And once the user selects it, it would look like this:

amrit@system25:~/ros2_ws$ ros2 topic echo
ros2 topic echo > /chatter <args>

Or

can make it look better with just

amrit@system25:~/ros2_ws$ ros2 topic echo
> /chatter <args>

User can type the additional arguments afterros2 topic echo > /chatteror > /chatter and hit enter to execute.

Then I’d update the five topic verbs (echo, info, hz, bw, type). Each verb would store a reference to its parser in add_arguments() using self._parser = parser, use the new helper instead of interactive_select, and then reparse the user input with self._parser.parse_args(tokens, namespace=args) so that any extra flags get handled exactly the same way as if they were typed on the original command line.

And

  • This will solve the problem of adding the arguments in the interactive, but the shell still will record only the ros2 topic echo in the history. How should I approach it?
  • Is storing self._parser = parser in add_arguments() okay? and using shlex.split() to tokenize the user input before re-parsing?

I did think of this approach earlier, but it won't store it in the history, so dropped the idea.

happy to adjust based on feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cannot configure optional argument after fzf-based interactive selection

3 participants